package com.parp;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.graphics.Canvas;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import com.parp.visuals.CircleVisual;
import com.parp.visuals.LineVisual;
import com.parp.visuals.ScopeVisual;
import com.parp.visuals.Visual;
import com.utils.SoundManager;

public class TouchView extends View
{
	private long lastDraw;
	private long lastMotion;

	private SoundManager soundManager;
	private int currentSound = 0;
	private Map<String, Integer> soundsMap;
	private Map<Integer, Integer> eventToSound;
	private final Random randomGen = new Random(System.currentTimeMillis());
	private SharedPreferences sp;
	private OnSharedPreferenceChangeListener cl;
	
	private Map<Integer, float[]> drawPositions;
	List<Visual> visual;

	public TouchView(Context context)
	{
		this(context, null, 0);
	}
	public TouchView(Context context, AttributeSet attrs)
	{
		this(context, attrs, 0);
	}

	public TouchView(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);
		soundManager = new SoundManager(context);
		String[] sounds = context.getResources().getStringArray(R.array.soundValueArray);
		soundsMap = new HashMap<String, Integer>();
		for(int i=0; i<sounds.length; i++)
		{
			soundsMap.put(sounds[i], i);
			soundManager.addSound(i, context.getResources().getIdentifier(sounds[i], "raw", "com.parp"));
		}

		eventToSound = new HashMap<Integer, Integer>();
		
		drawPositions = new HashMap<Integer, float[]>();
		
		visual = new ArrayList<Visual>();
		
		visual.add(new CircleVisual());
		visual.add(new LineVisual());
		
		lastDraw = lastMotion = SystemClock.uptimeMillis();
		/*mIcon = context.getResources().getDrawable(R.drawable.icon);
		mIcon.setBounds(0, 0, mIcon.getIntrinsicWidth(), mIcon.getIntrinsicHeight());*/
		
		sp = PreferenceManager.getDefaultSharedPreferences(context);
		updateOptions(sp);
		cl = new OnSharedPreferenceChangeListener () {
	        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
	        	updateOptions(sharedPreferences);
	        }
	    };
		sp.registerOnSharedPreferenceChangeListener(cl);
	}
	
	public void updateOptions(SharedPreferences sharedPreferences)
	{
		boolean enableVis = sharedPreferences.getBoolean("enableVisuals", true);
		boolean drawCircle = sharedPreferences.getBoolean("enableCircles", true);
    	int numCircles = sharedPreferences.getInt("numCircle", 10);
    	boolean drawLines = sharedPreferences.getBoolean("enableLines", true);
    	String soundName = sharedPreferences.getString("soundOption", "quickfart");
    	
    	Log.i("PARP", "" + drawCircle + " " + numCircles);
    	
    	currentSound = soundsMap.get(soundName);
    	
    	for(Visual vis : visual)
    	{
    		if(vis instanceof CircleVisual)
    		{
    			vis.enable(drawCircle && enableVis);
    		}
    		else if(vis instanceof LineVisual)
    		{
    			vis.enable(drawLines && enableVis);
    		}
    		else if(vis instanceof ScopeVisual)
    		{
    			vis.enable(false);
    		}
    	}
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev)
	{
		final int action = ev.getAction();

		switch (action & MotionEvent.ACTION_MASK)
		{
			case MotionEvent.ACTION_DOWN:
			{
				float x = ev.getX(0);
				float y = ev.getY(0);
				float rate = (0.5f + ((this.getHeight() - y) / this.getHeight())) + (0.1f - randomGen.nextFloat() * 0.2f);
				float volume = x / this.getWidth();
				
				soundManager.playSoundAndStopOthers(currentSound);
				eventToSound.put(ev.getPointerId(0), currentSound);
				soundManager.setSoundPropertiesPlaying(currentSound, rate, volume, volume);
				
				Log.i("PARP", "Playing Sound " + currentSound);
				break;
			}

			case MotionEvent.ACTION_MOVE:
			{
				int id = 0;
				float x = 0;
				float y = 0;
				float rate = 1;
				float volume = 1;
				long timeLapse = SystemClock.uptimeMillis() - lastMotion;
				//For each pointer
				for (int i = 0; i < ev.getPointerCount(); i++)
				{
					//That has a sound associated to it
					if(eventToSound.get(ev.getPointerId(i)) != null) {
						id = ev.getPointerId(i);
						x = ev.getX(id);
						y = ev.getY(id);
						rate = (0.5f + ((this.getHeight() - y) / this.getHeight())) + (0.1f - randomGen.nextFloat() * 0.2f);
						volume = x / this.getWidth();
						soundManager.setSoundPropertiesPlaying(eventToSound.get(id), rate, volume, volume);
						
						float[] position = {x,y};
						drawPositions.put(id, position);
						
						for(Visual v : visual) {
							v.motionUpdate(id, x, y, timeLapse,this.getHeight());
						}
					}
				}
				
				invalidate();
				
				break;
			}

			case MotionEvent.ACTION_UP:
			{
				//if the pointer has a sound associated to it
				if(eventToSound.get(ev.getPointerId(0)) != null) {
					soundManager.pauseAllPlayingSounds();
					eventToSound.remove(ev.getPointerId(0));
					Log.i("PARP", "Stopping Sound " + currentSound);
				}
				for(Visual v : visual) {
					v.up();
				}
				break;
			}

			case MotionEvent.ACTION_CANCEL:
			{
				break;
			}

			case MotionEvent.ACTION_POINTER_DOWN:
			{
				//If it is the second pointer down
				if(!(ev.getPointerCount() > 2)) {
					final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
					final int pointerId = ev.getPointerId(pointerIndex);
					Log.i("PARP", "Playing sound for pointer " + pointerIndex + " " + pointerId + " " + eventToSound.get(pointerId));
					soundManager.playSoundAndStopOthers(currentSound);
					eventToSound.put(pointerId, currentSound);
				}
				break;
			}

			case MotionEvent.ACTION_POINTER_UP:
			{
				final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
				final int pointerId = ev.getPointerId(pointerIndex);
				//If the pointer has a sound associated with it
				if(eventToSound.get(pointerId) != null) {
					Log.i("PARP", "Stopping sound for pointer " + pointerIndex + " " + pointerId + " " + eventToSound.get(pointerId));
					soundManager.pauseAllPlayingSounds();
					eventToSound.remove(pointerId);
				}
				break;
			}
		}
		return true;
	}

	@Override
	public void onDraw(Canvas canvas)
	{
		long timeLapse = SystemClock.uptimeMillis() - lastDraw;
		for(int id : drawPositions.keySet())
		{
			for(Visual v : visual) {
				v.drawVisual(id, canvas, drawPositions.get(id)[0], drawPositions.get(id)[1], timeLapse);
			}
		}
		lastDraw = SystemClock.uptimeMillis();
		super.onDraw(canvas);
		
	}
}